// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

/*
 * @Author: Li Zhaoni 17789284585@163.com
 * @Date: 2024-07-24 10:55:50
 * @LastEditors: qiulin 1746365080@qq.com
 * @LastEditTime: 2025-01-08 19:46:36
 * @FilePath: \SGFEM\Import\BDFImport\NastranBDFParserBase.cpp
 */
#include "BDFParserBase.h"

#include <iostream>
#include <sstream>

#include <boost/algorithm/string.hpp>

#include "Utility/Exception/SGException.h"
#include "Utility/Logging/SGLogger.h"

#include "DataStructure/Common/Constant.h"
using namespace SG::Import;
using namespace SG::DataStructure::FEM;

/// @brief 虚节点个数，根据此个数进行ID的生成
static SG::DataStructure::Common::I64 VIRTUAL_GRID_COUNT = 0;

void BDF::parseCaseControlLine (const std::string& inputLine, _OUT Subcase::ControlInfo& controlInfo)
{
    // 检查是否存在等号
    std::size_t const lastEqualSignIndex = inputLine.rfind ('=');  ///< 最后一个等号的位置

    if (lastEqualSignIndex == std::string::npos)
    {
        if (parseDoubleField (inputLine, controlInfo))
        {
            return;
        }

        SGInfo << "[Function: NBDF::parseCaseControlLine] No equal sign found in the input line.";
        SGInfo << "inputLine: " << inputLine;
        return;
    }

    // 清空全局解析结构体的键值和可选参数
    controlInfo.m_mapKeys.clear ();
    controlInfo.m_vecKeys.clear ();

    // 找到括号的位置
    std::size_t const leftParenthesisIndex  = inputLine.find ('(');  ///< 左括号的位置
    std::size_t const rightParenthesisIndex = inputLine.find (')');  ///< 右括号的位置

    // 存在中间部分
    if (leftParenthesisIndex != std::string::npos && rightParenthesisIndex != std::string::npos)
    {
        // 提取左侧字符串并查找等号
        std::string keyPart = inputLine.substr (0, leftParenthesisIndex);  ///< 键的部分

        // 提取等号右侧的字符串
        std::string valuePart = inputLine.substr (lastEqualSignIndex + 1);  ///< 值的部分

        // 去除前后的空白字符
        boost::trim (keyPart);
        boost::trim (valuePart);

        // 存储主键和值
        controlInfo.m_Key   = keyPart;
        controlInfo.m_Vaule = valuePart;

        // 中间部分解析
        std::string const innerContent =
            inputLine.substr (leftParenthesisIndex + 1, rightParenthesisIndex - leftParenthesisIndex - 1);  ///< 括号内的内容
        std::istringstream stringStream (innerContent);                                                     ///< 字符串流，用于分割内容
        std::string        token;                                                                           ///< 临时存储每个分割后的字符串

        // 以逗号分割中间部分
        while (std::getline (stringStream, token, ','))
        {
            // 去除空白字符
            boost::trim (token);
            std::size_t const equalSignInsideIndex = token.find ('=');  ///< 括号内键值对的等号位置

            if (equalSignInsideIndex != std::string::npos)
            {
                // 存储带等号的参数到 m_mapKeys
                std::string mapKey = token.substr (0, equalSignInsideIndex);     ///< 键
                boost::trim (mapKey);
                std::string mapValue = token.substr (equalSignInsideIndex + 1);  ///< 值
                boost::trim (mapValue);

                // 将键值对存储到映射中
                controlInfo.m_mapKeys[mapKey] = mapValue;
            }
            else
            {
                // 存储不带等号的参数到 m_vecKeys
                controlInfo.m_vecKeys.push_back (token);
            }
        }
        return;  // 解析成功，退出函数
    }

    // 暂时对SET类型进行特殊处理  e.g.: SET 1 = 101,THRU,104
    if (boost::starts_with (boost::trim_copy (inputLine), "SET"))
    {
        // 提取主键和值
        std::string simpleKey = inputLine.substr (0, lastEqualSignIndex);                              ///< SET 1
        boost::trim (simpleKey);
        std::string const simpleValue = boost::trim_copy (inputLine.substr (lastEqualSignIndex + 1));  ///< 101,THRU,104

        std::string const setId = boost::trim_copy (simpleKey.substr (3));

        controlInfo.m_Key            = "SET";
        controlInfo.m_mapKeys[setId] = simpleValue;

        return;  // 解析成功，退出函数
    }

    // 没有括号的情况
    if (leftParenthesisIndex == std::string::npos && rightParenthesisIndex == std::string::npos)
    {
        // 提取主键和值
        std::string simpleKey   = inputLine.substr (0, lastEqualSignIndex);   ///< 简单的键
        std::string simpleValue = inputLine.substr (lastEqualSignIndex + 1);  ///< 简单的值

        // 去除前后的空白字符
        boost::trim (simpleKey);
        boost::trim (simpleValue);

        // 存储主键和值
        controlInfo.m_Key   = simpleKey;
        controlInfo.m_Vaule = simpleValue;
        return;  // 解析成功，退出函数
    }

    SGError << "[Function: NBDF::parseCaseControlLine] Input contains unbalanced parentheses";
    SGError << "inputLine: " << inputLine;
    // 抛出异常：输入字符串包含不平衡的括号
    throw std::logic_error ("parseCaseControlLine: Input contains unbalanced parentheses");
}

bool BDF::parseDoubleField (const std::string& inputLine, _OUT Subcase::ControlInfo& controlInfo)
{
    std::string dealStr = inputLine;
    // 去除字符串两端的空白字符
    boost::trim (dealStr);

    // 查找第一个空格的位置
    std::size_t const firstBlank = dealStr.find (' ');

    // 查找最后一个空格的位置
    std::size_t const lastBlank = dealStr.rfind (' ');

    // 如果第一个空格和最后一个空格位置相同，则说明只有一个空格
    if (firstBlank == lastBlank)
    {
        controlInfo.m_Key   = dealStr.substr (0, firstBlank);
        controlInfo.m_Vaule = dealStr.substr (lastBlank + 1);
        return true;
    }
    // 如果没有找到空格，则认为输入行格式错误
    if (firstBlank == std::string::npos)
    {
        SGError << ("[Function: BDF::parseDoubleField] Input donot contains  blank");
        SGError << "inputLine: " << inputLine;
        return false;
    }
    // 如果存在多个空格，则检查中间部分是否全是空格

    std::string midStr  = dealStr.substr (firstBlank + 1, lastBlank - firstBlank - 1);
    bool const  isEmpty = std::all_of (midStr.begin (), midStr.end (), [] (char c) { return c == ' '; });

    if (!isEmpty)
    {
        SGError << ("[Function: BDF::parseDoubleField] Input contains n blank");
        SGError << "inputLine: " << inputLine;
        return false;
    }

    controlInfo.m_Key   = dealStr.substr (0, firstBlank);
    controlInfo.m_Vaule = dealStr.substr (lastBlank + 1);
    return true;
}

bool BDF::divideBulkEntry (std::vector<std::string>& BulkCompleteLine, std::vector<std::string>& BulkField)
{
    std::size_t const entrySize = BulkCompleteLine.size ();  // 获取词条文本行数
    if (entrySize == 0)
    {
        SGWarn << "[BDF::divideBulkEntry] LineEntryInfo size ==0.";
        return false;    // 如果没有行，返回 false
    }

    BulkField.clear ();  // 清空分割后的行容器
    BulkField.reserve (entrySize * 10);

    BDF::BDFFORMAT last = BDFFORMAT_FREE;

    // 遍历每一行
    for (std::size_t i = 0; i < entrySize; i++)
    {
        auto&                    curLine = BulkCompleteLine[i];                                                     // 当前行
        std::vector<std::string> vlineStr (SIGNELINE_FIELDCOUNT, "");                                               // 当前文本行的分割结果
        auto                     lineFormat = last == BDFFORMAT_SET ? BDFFORMAT_SET : getBulkLineFormat (curLine);  // 获取当前行的格式
        std::size_t              lineSize   = curLine.size ();                                                      // 获取当前行的长度

        std::istringstream ss (curLine);    // 用于分割当前行的字符串流
        std::string        token;           // 存储分割得到的字符串
        int                entryIndex = 0;  // 当前分割结果的索引

        // 增加对制表符分割的处理，
        if (BulkCompleteLine[i].find ('\t') != std::string::npos)
        {
            std::vector<std::string> result;
            // 使用 Boost 的 split 分割字符串
            boost::split (result, BulkCompleteLine[i], boost::is_any_of ("\t"));
            if (result.size () > 10)
            {
                std::string str = BulkCompleteLine[i] + " contain \\t,but size > 10";
                throw std::runtime_error (str);
            }
            result.resize (10);

            BulkField.insert (BulkField.end (), result.begin (), result.end ());
            continue;
        }

        switch (lineFormat)
        {
        case BDFFORMAT_FREE:                   // 自由格式
            while (std::getline (ss, token, ','))
            {
                vlineStr[entryIndex] = token;  // 将分割得到的字符串存入 vlineStr
                entryIndex++;
            }
            break;

        case BDFFORMAT_SMALL:   // 小格式
            if (lineSize > 80)
            {
                lineSize = 80;  // 限制行长度为 80 字符
            }

            for (std::size_t curStrindex = 0; curStrindex < lineSize; curStrindex += SMALLFOEMATSZIE)
            {
                vlineStr[entryIndex] = curLine.substr (curStrindex, SMALLFOEMATSZIE);  // 切割小格式行
                entryIndex++;
            }
            break;

        case BDFFORMAT_LARGE:   // 大格式
            if (lineSize > 80)
            {
                lineSize = 80;  // 限制行长度为 80 字符
            }

            // 切割第一行
            vlineStr[entryIndex] = curLine.substr (0, ENTRYSZIE);  // 获取第一部分
            ++entryIndex;

            for (std::size_t curStrindex = ENTRYSZIE; curStrindex < lineSize; curStrindex += LARGEFOEMATSZIE)
            {
                vlineStr[entryIndex] = curLine.substr (curStrindex, LARGEFOEMATSZIE);  // 切割大格式行
                entryIndex++;
            }

            entryIndex = 5;  // 第一行可能切割不出 5 个字段

            // 如果当前行不是最后一行，继续读取下一行
            if (i != (entrySize - 1))
            {
                curLine  = BulkCompleteLine[++i];                        // 读取下一行
                lineSize = curLine.size () > 80 ? 80 : curLine.size ();  // 更新当前行的长度

                for (std::size_t curStrindex = ENTRYSZIE; curStrindex < lineSize; curStrindex += LARGEFOEMATSZIE)
                {
                    vlineStr[entryIndex] = curLine.substr (curStrindex, LARGEFOEMATSZIE);  // 切割剩余部分
                    entryIndex++;
                }
            }
            break;

        case BDFFORMAT_SET:
            last = BDFFORMAT_SET;
            if (i == 0)
            {
                std::size_t const eqs = curLine.find ('=');
                // 先按照等号分割 等号前面的是ID
                if (eqs != std::string::npos)
                {
                    BulkField.push_back (
                        boost::trim_copy (boost::replace_all_copy (boost::to_upper_copy (curLine.substr (0, eqs)), "SET", "")));

                    std::string back = curLine.substr (eqs + 1);
                    // 以逗号分割的情况
                    if (boost::contains (back, ","))
                    {
                        std::vector<std::string> result;
                        boost::split (result, back, boost::is_any_of (","));
                        for (auto&& i : result)
                        {
                            std::string c = boost::trim_copy (boost::to_upper_copy (i));
                            if (!c.empty ())
                            {
                                // 如果是THRU格式的，直接添加
                                if (boost::icontains (c, "THRU"))
                                {
                                    std::vector<std::string> subresult;
                                    boost::split (subresult, c, boost::is_any_of (" "));
                                    if (subresult.size () == 3)
                                    {
                                        for (auto&& j : subresult)
                                        {
                                            std::string cc = boost::trim_copy (boost::to_upper_copy (j));
                                            if (!cc.empty ())
                                            {
                                                BulkField.push_back (cc);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        BulkField.push_back (c);
                                    }
                                }
                                else
                                {
                                    BulkField.push_back (c);
                                }
                            }
                        }
                        break;
                    }

                    std::vector<std::string> result;
                    boost::split (result, boost::trim_copy (back), boost::is_any_of (" "));
                    if (result.size () == 3 && boost::icontains (back, "THRU"))
                    {
                        for (auto&& i : result)
                        {
                            std::string c = boost::trim_copy (boost::to_upper_copy (i));
                            if (!c.empty ())
                                BulkField.push_back (c);
                        }
                    }
                }
            }
            else
            {
                if (boost::contains (curLine, ","))
                {
                    std::vector<std::string> result;
                    boost::split (result, curLine, boost::is_any_of (","));
                    for (auto&& i : result)
                    {
                        std::string c = boost::trim_copy (boost::to_upper_copy (i));
                        if (!c.empty ())
                        {
                            // 如果是THRU格式的，直接添加
                            if (boost::icontains (c, "THRU"))
                            {
                                std::vector<std::string> subresult;
                                boost::split (subresult, c, boost::is_any_of (" "));
                                if (subresult.size () == 3)
                                {
                                    for (auto&& j : subresult)
                                    {
                                        std::string cc = boost::trim_copy (boost::to_upper_copy (j));
                                        if (!cc.empty ())
                                        {
                                            BulkField.push_back (cc);
                                        }
                                    }
                                }
                                else
                                {
                                    BulkField.push_back (c);
                                }
                            }
                            else
                            {
                                BulkField.push_back (c);
                            }
                        }
                    }
                }
                else
                {
                    std::vector<std::string> result;
                    boost::split (result, boost::trim_copy (curLine), boost::is_any_of (" "));

                    for (auto&& i : result)
                    {
                        std::string c = boost::trim_copy (boost::to_upper_copy (i));
                        if (c != "")
                        {
                            BulkField.push_back (c);
                        }
                    }
                }
            }

            break;

        default:
            return false;  // 如果格式不符合，返回 false
            break;
        }

        // 将分割得到的结果添加到 m_SplitLine 容器中
        BulkField.insert (BulkField.end (), vlineStr.begin (), vlineStr.end ());
    }
    return true;  // 成功完成分割，返回 true
}

bool BDF::covertToScientificNotation (std::string& str)
{
    boost::trim (str);
    std::size_t       Pos       = 0;
    bool              isFloat   = false;
    std::size_t const strLength = str.length ();
    if (str.empty ())
    {
        return isFloat;
    }
    if ('.' == str[0])
    {
        isFloat = true;
    }
    for (std::size_t i = 1; i < strLength; i++)
    {
        Pos++;
        switch (str[i])
        {
        case '-':
        case '+':
            if (str[i - 1] != 'e' && str[i - 1] != 'E')
            {
                str.insert (Pos, "e");
            }
            return isFloat;
        case '.':
            isFloat = true;
        default:
            break;
        }
    }
    return isFloat;
}

SG::DataStructure::Common::Real BDF::convertToReal (std::string& str)
{
    static SG::DataStructure::Common::Real returnDouble = 0.0;
    returnDouble                                        = 0.0;
    try
    {
        covertToScientificNotation (str);
        returnDouble = std::stod (str);
    }
    catch (const std::exception& e)
    {
        // std::cout << "BDF parse to real failed : " << e.what () << " -> " << str << "\n";
        throw SG::Utility::ParserError ("BDF parse to real failed: " + std::string (e.what ()) + " -> " + str);
    }
    return returnDouble;
}

SG::DataStructure::Common::I64 BDF::convertToI64 (std::string& str)
{
    static SG::DataStructure::Common::I64 returnI64 = 0.0;
    returnI64                                       = 0;
    try
    {
        covertToScientificNotation (str);
        returnI64 = std::stoll (str);
    }
    catch (const std::exception& e)
    {
        // std::cout << "BDF parse to int64 failed : " << e.what () << " -> " << str << "\n";
        throw SG::Utility::ParserError ("BDF parse to int64 failed: " + std::string (e.what ()) + " -> " + str);
    }
    return returnI64;
}

BDF::BDFFORMAT BDF::getBulkLineFormat (std::string& StrLine)
{
    for (auto c : StrLine)
    {
        switch (c)
        {
        case ',':
            return BDFFORMAT_FREE;
            break;  // 逗号,
        case '*':
            return BDFFORMAT_LARGE;
            break;  // 星号*
        case '=':
            return BDFFORMAT_SET;
            break;
        default:
            break;
        }
    }
    return BDFFORMAT_SMALL;
}

int BDF::findNonEmptyIndex (const std::vector<std::string>& data, size_t row)
{
    const size_t elementsPerRow = 10;                                           // 每行10个元素
    const size_t startIdx       = row * elementsPerRow + (elementsPerRow - 2);  // 倒数第二个元素的索引

    // 从倒数第二个元素开始向前查找到第二个元素
    for (size_t curIndex = startIdx; curIndex > row * elementsPerRow; --curIndex)
    {
        bool const isEmpty = std::all_of (data[curIndex].begin (), data[curIndex].end (), [] (char c) { return c == ' '; });
        if (!isEmpty)
        {
            return static_cast<int> (curIndex);
        }
    }

    return -1;  // 如果这一行都是空字符串，返回-1
}

std::vector<std::string> BDF::divideFreeForm (std::string& inputStr)
{
    std::vector<std::string> result;

    boost::trim (inputStr);  // 去除前后的空白字符
    // 替换逗号和空格为统一分隔符（空格）
    boost::replace_all (inputStr, ",", " ");

    // 按空格分割字符串
    boost::split (result, inputStr, boost::is_any_of (" "), boost::token_compress_on);

    return result;
}

SG::DataStructure::Common::I64 BDF::getVirtualGridId ()
{
    return (++VIRTUAL_GRID_COUNT) + SG::DataStructure::Common::VIRTUAL_GRID_ID_ORIGIN;
}

bool ::SG::Import::BDF::is_all_space (std::string& str)
{
    return std::all_of (str.begin (), str.end (), [] (char c) { return c == ' '; });
}
